﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using FXC.SL.CS.Util;
using FXC.SL.FXCenterService;
using Telerik.Windows.Controls.Charting;
using FXC.SL.Interface;
using System.Windows.Media.Imaging;
using System.IO;
using FXC.SL.UserControls.Window;
using FXC.SL.CS.ChartUtil;

namespace FXC.SL.UserControls.FXCChart
{
    public partial class FXChart : UserControl, IChart
    {
        private string _productName;
        private PeriodType _periodType = PeriodType.T_1D;
        private ChartType _chartType = ChartType.CandleStick;
        private SeriesMapping _mainSeriesMapping = new SeriesMapping();
        private SeriesMapping _volumnSeriesMapping = new SeriesMapping();
        private ChartArea chartArea = new ChartArea();
        private bool _isShowVolume = false;
        private int zoom = 0;

        public ChartTheme FXVChartTheme
        {
            get { return null; }
            set
            {
                
            }
        }

        //private SolidColorBrush _backgroundColor = new SolidColorBrush(Constants.DefaultBackgroundColor);
        //private SolidColorBrush _foregroundColor = new SolidColorBrush(Constants.DefaultForegroundColor);
        //private SolidColorBrush _gridColor = new SolidColorBrush(Constants.DefaultGridColor);
        //private SolidColorBrush _barStrokeColor = new SolidColorBrush(Constants.DefaultBarStrokeColor);
        //private SolidColorBrush _barFillColor = new SolidColorBrush(Constants.DefaultBarFillColor);
        //private SolidColorBrush _lineTypeColor = new SolidColorBrush(Constants.DefaultLineTypeColor);
        //private SolidColorBrush _volumeColor = new SolidColorBrush(Constants.DefaultVolumeColor);
        
        FXCenterService.FXCServiceClient proxy = FXCServiceClientManager.CreateProxy();

        SaveFileDialog _saveImgFileDialgue = new SaveFileDialog();

        public FXChart(string ProductCode, PeriodType periodType)
        {
            InitializeComponent();
            _productName = ProductCode;
            _periodType = periodType;
            InitialChartArea();
            InitialSeries();
            GetDataFromService();
        }

        private void InitialSeries()
        {
            RebindMainSeries(new CandleStickSeriesDefinition());
            RebindVolumeSeries();
        }

        private void InitialChartArea()
        {
            chartArea.EnableAnimations = false;
            chartArea.EnableStripLinesAnimation = false;
            chartArea.LabelFormatBehavior = LabelFormatBehavior.None;

            chartArea.AxisX.LabelStep = 20;
            chartArea.AxisX.LabelRotationAngle = -30;
            //chartArea.AxisY.DefaultLabelFormat = GetLabelFormatByProductCode();
            
            //chartArea.Foreground = _foregroundColor;

            chartArea.AxisX.DefaultLabelFormat = "yyyy-MM-dd HH:mm";

            chartArea.ZoomScrollSettingsX.RangeStart = Constants.StandardZoom;
            chartArea.ZoomScrollSettingsX.RangeEnd = 1;
            
            Style gridSytle = new Style(typeof(System.Windows.Shapes.Rectangle));
            //gridSytle.Setters.Add(new Setter(System.Windows.Shapes.Rectangle.FillProperty, _gridColor));

            Style backgroudSytle = new Style(typeof(System.Windows.Shapes.Rectangle));
            //backgroudSytle.Setters.Add(new Setter(System.Windows.Shapes.Rectangle.FillProperty, _backgroundColor));

            Style itemLabelStyle = new System.Windows.Style(typeof(TextBlock));
            //itemLabelStyle.Setters.Add(new Setter(TextBlock.ForegroundProperty, _foregroundColor));

            chartArea.AxisY.AxisStyles.StripLineStyle = backgroudSytle;
            chartArea.AxisY.AxisStyles.AlternateStripLineStyle = gridSytle;

            chartArea.AxisY.AxisStyles.ItemLabelStyle = itemLabelStyle;
            chartArea.AxisX.AxisStyles.ItemLabelStyle = itemLabelStyle;

            chartArea.ZoomScrollSettingsX.ScrollMode = ScrollMode.ScrollOnly;


            //Step depends on PeriodType 

            var volumeAxis = new AxisY();
            volumeAxis.AxisName = "Volumn";
            volumeAxis.AutoRange = false;
            volumeAxis.MinValue = 0;
            volumeAxis.MaxValue = 30000; //TODO: 最大值要和ProductCode有关
            volumeAxis.Step = 100;
            volumeAxis.Visibility = Visibility.Collapsed;
            chartArea.AdditionalYAxes.Add(volumeAxis);

            rcProduct.DefaultView.ChartLegend.Visibility = System.Windows.Visibility.Collapsed;
            rcProduct.DefaultView.ChartArea = chartArea;
        }

        private string GetLabelFormatByProductCode()
        {
            //TODO: Get Label format from DB.
            //LabelFormat depend on ProductCode
            return "N5";
        }

        private void RebindMainSeries(ISeriesDefinition seriesDefinition)
        {
            if (rcProduct.SeriesMappings.Contains(_mainSeriesMapping))
            {
                rcProduct.SeriesMappings.Remove(_mainSeriesMapping);
            }
            
            _mainSeriesMapping.SeriesDefinition = seriesDefinition;
            _mainSeriesMapping.SeriesDefinition.Appearance.StrokeThickness = 1;
            if (seriesDefinition is SplineSeriesDefinition)
            {
                //_mainSeriesMapping.SeriesDefinition.Appearance.Stroke = _lineTypeColor;
                _mainSeriesMapping.SeriesDefinition.ShowItemLabels = false;
            }
            else
            {
            //    _mainSeriesMapping.SeriesDefinition.Appearance.Stroke = _barStrokeColor;
            }
            
            //_mainSeriesMapping.SeriesDefinition.Appearance.Fill = _barFillColor;
            _mainSeriesMapping.SeriesDefinition.Appearance.Cursor = Cursors.Hand;

            _mainSeriesMapping.SeriesDefinition.ShowItemToolTips = true;

            var imHigh = new ItemMapping("HighPrice", DataPointMember.High);
            var imLow = new ItemMapping("LowPrice", DataPointMember.Low);
            var imOpen = new ItemMapping("OpenPrice", DataPointMember.Open);
            var imClose = new ItemMapping("ClosePrice", DataPointMember.Close);
            //var imXDate = new ItemMapping("ID", DataPointMember.XValue);
            var imYDate = new ItemMapping("ClosePrice", DataPointMember.YValue);
            var imZDate = new ItemMapping("ProcessDateTime", DataPointMember.XCategory);

            _mainSeriesMapping.ItemMappings.Add(imHigh);
            _mainSeriesMapping.ItemMappings.Add(imLow);
            _mainSeriesMapping.ItemMappings.Add(imOpen);
            _mainSeriesMapping.ItemMappings.Add(imClose);
            //_mainSeriesMapping.ItemMappings.Add(imXDate);
            _mainSeriesMapping.ItemMappings.Add(imYDate);
            _mainSeriesMapping.ItemMappings.Add(imZDate);

            rcProduct.SeriesMappings.Add(_mainSeriesMapping);
        }

        private void RebindVolumeSeries()
        {
            //加第二个Series TODO: Style不对，宽度有问题
            if (rcProduct.SeriesMappings.Contains(_volumnSeriesMapping))
            {
                rcProduct.SeriesMappings.Remove(_volumnSeriesMapping);
            }
  
            _volumnSeriesMapping.SeriesDefinition = new BarSeriesDefinition();
            _volumnSeriesMapping.SeriesDefinition.ShowItemToolTips = true;
            _volumnSeriesMapping.SeriesDefinition.ShowItemLabels = false;
            //_volumnSeriesMapping.SeriesDefinition.Appearance.Fill = _volumeColor;
            //_volumnSeriesMapping.SeriesDefinition.Appearance.Stroke = _volumeColor;
            _volumnSeriesMapping.SeriesDefinition.Appearance.StrokeThickness = 1;
            _volumnSeriesMapping.SeriesDefinition.AxisName = "Volumn";
            _volumnSeriesMapping.ItemMappings.Add(new ItemMapping("ProcessDateTime", DataPointMember.XCategory));
            _volumnSeriesMapping.ItemMappings.Add(new ItemMapping("Volume", DataPointMember.YValue));

            if (_isShowVolume)
            {
                rcProduct.SeriesMappings.Add(_volumnSeriesMapping);
            }
        }

        private void BindData(List<FXData> itemsSource)
        {
            rcProduct.ItemsSource = itemsSource;
        }

        private void GetDataFromService()
        {
            proxy.GetFXCDataCompleted += (o, e) =>
            {
                if (e.Error == null)
                {
                    BindData(e.Result.ToList());
                }
                else
                {
                }
            };
            proxy.GetFXCDataAsync(_productName, this.PeriodType.ToString().Substring(2));
        }

        public bool IsIndicatorEnabled
        {
            get;
            set;
        }

        #region Public Methods

        #endregion

        #region IChart Members

        public void SaveToImage()
        {
            _saveImgFileDialgue.DefaultExt = ".bmp";
            _saveImgFileDialgue.Filter = "Bitmap(*.bmp)|*.bmp";
            _saveImgFileDialgue.FilterIndex = 2;
            bool? dialogResult = _saveImgFileDialgue.ShowDialog();
            if (dialogResult == true)
            {
                WriteableBitmap btm = new WriteableBitmap((int)rcProduct.ActualWidth, (int)rcProduct.ActualHeight);
                btm.Render(rcProduct, null);
                btm.Invalidate();

                using (Stream stream = _saveImgFileDialgue.OpenFile())
                {
                    byte[] buffer = ImageUtil.GetBuffer(btm);
                    stream.Write(buffer, 0, buffer.Length);
                }
            }
        }

        public void SaveData()
        {
            List<FXData> lstData = rcProduct.ItemsSource as List<FXData>;
            if (lstData == null || lstData.Count == 0)
            {
                MessageBox.Show("当前图表没有任何数据可以被导出");
                return;
            }
            _saveImgFileDialgue.DefaultExt = ".csv";
            _saveImgFileDialgue.Filter = "CSV(*.csv)|*.csv";
            _saveImgFileDialgue.FilterIndex = 2;
            bool? dialogResult = _saveImgFileDialgue.ShowDialog();
            if (dialogResult == true)
            {
                System.Text.StringBuilder sbContent = new System.Text.StringBuilder();
                for (int i = 0; i < lstData.Count; i++)
                {
                    sbContent.Append(string.Format("ID={0},OpenPrice={1},ClosePrice={2},HighPrice={3},LowPrice={4},ProcessDateTime={5};", lstData[i].ID, lstData[i].OpenPrice,
                        lstData[i].ClosePrice, lstData[i].HighPrice, lstData[i].LowPrice, lstData[i].ProcessDateTime));
                }
                using (Stream stream = _saveImgFileDialgue.OpenFile())
                {
                    Byte[] fileContent = System.Text.UTF8Encoding.UTF8.GetBytes(sbContent.ToString());
                    stream.Write(fileContent, 0, fileContent.Length);
                    stream.Close();
                }
            }
        }
        /*
        public Color BackgroundColor
        {
            get
            {
                return _backgroundColor.Color;
            }
            set
            {
                if (_backgroundColor.Color != value)
                {
                    _backgroundColor = new SolidColorBrush(value);
                    Style backgroudSytle = new Style(typeof(System.Windows.Shapes.Rectangle));
                    backgroudSytle.Setters.Add(new Setter(System.Windows.Shapes.Rectangle.FillProperty, _backgroundColor));
                    chartArea.AxisY.AxisStyles.StripLineStyle = backgroudSytle;
                }
            }
        }

        public Color ForegroundColor
        {
            get
            {
                return _foregroundColor.Color;
            }
            set
            {
                if (_foregroundColor.Color != value)
                {
                    _foregroundColor = new SolidColorBrush(value);
                    Style itemLabelStyle = new System.Windows.Style(typeof(TextBlock));
                    itemLabelStyle.Setters.Add(new Setter(TextBlock.ForegroundProperty, _foregroundColor));

                    chartArea.AxisY.AxisStyles.ItemLabelStyle = itemLabelStyle;
                    chartArea.AxisX.AxisStyles.ItemLabelStyle = itemLabelStyle;
                }
            }
        }

        public Color GridColor
        {
            get
            {
                return _gridColor.Color;
            }
            set
            {
                if (_gridColor.Color != value)
                {
                    _gridColor = new SolidColorBrush(value);
                    Style gridSytle = new Style(typeof(System.Windows.Shapes.Rectangle));
                    gridSytle.Setters.Add(new Setter(System.Windows.Shapes.Rectangle.FillProperty, _gridColor));

                    chartArea.AxisY.AxisStyles.AlternateStripLineStyle = gridSytle;
                }
            }
        }

        public Color BarStrokeColor
        {
            get
            {
                return _barStrokeColor.Color;
            }
            set
            {
                if (_barStrokeColor.Color != value)
                {
                    ISeriesDefinition seriesDefinition = _mainSeriesMapping.SeriesDefinition;
                    if (seriesDefinition is CandleStickSeriesDefinition || seriesDefinition is StickSeriesDefinition)
                    {
                        _barStrokeColor = new SolidColorBrush(value);

                        if (seriesDefinition is CandleStickSeriesDefinition)
                        {
                            RebindMainSeries(new CandleStickSeriesDefinition());
                        }
                        else
                        {
                            RebindMainSeries(new StickSeriesDefinition());
                        }

                    }
                }
            }
        }

        public Color BarFillColor
        {
            get
            {
                return _barFillColor.Color;
            }
            set
            {
                if (_barFillColor.Color != value)
                {
                    _barFillColor = new SolidColorBrush(value);

                    ISeriesDefinition seriesDefinition = _mainSeriesMapping.SeriesDefinition;
                    if (seriesDefinition is CandleStickSeriesDefinition)
                    {
                        RebindMainSeries(new CandleStickSeriesDefinition());
                    }
                    else
                    {
                        RebindMainSeries(new StickSeriesDefinition());
                    }
                }
            }
        }

        public Color LineTypeColor
        {
            get
            {
                return _lineTypeColor.Color;
            }
            set
            {
                if (_lineTypeColor.Color != value)
                {
                    if (_mainSeriesMapping.SeriesDefinition is SplineSeriesDefinition)
                    {
                        _barStrokeColor = new SolidColorBrush(value);
                        RebindMainSeries(new SplineSeriesDefinition());
                    }
                }
            }
        }

        public Color VolumeColor
        {
            get
            {
                return _volumeColor.Color;
            }
            set
            {
                if (_volumeColor.Color != value)
                {
                    _volumeColor = new SolidColorBrush(value);
                    RebindVolumeSeries();
                }
            }
        }
        */
        public void ChangeZoomBig()
        {
            if (zoom < 4)
            {
                chartArea.ZoomScrollSettingsX.RangeStart += 0.05;
                chartArea.ZoomScrollSettingsX.RangeEnd = chartArea.ZoomScrollSettingsX.RangeEnd;
                zoom++;
            }
            
        }

        public void ChangeZoomSmall()
        {
            if (zoom > 0)
            {
                chartArea.ZoomScrollSettingsX.RangeStart -= 0.05;
                chartArea.ZoomScrollSettingsX.RangeEnd = chartArea.ZoomScrollSettingsX.RangeEnd;
                zoom--;
            }
        }

        public void Refresh()
        {
            InitialChartArea();
            InitialSeries();
            GetDataFromService();
        }

        public void ChangeBackgourd()
        {
            throw new NotImplementedException();
        }

        public void ChartPropertySetting()
        {
            ChartProperty formChartProperty = new ChartProperty(this);
            formChartProperty.ShowDialog();
            formChartProperty.Closed += new EventHandler<Telerik.Windows.Controls.WindowClosedEventArgs>(formChartProperty_Closed);
        }

        void formChartProperty_Closed(object sender, Telerik.Windows.Controls.WindowClosedEventArgs e)
        {
            //if (e.DialogResult.HasValue && e.DialogResult.Value)
            //{
            //    BackgroundColor = rcpBackground.SelectedColor;
            //    ForegroundColor = form.rcpForeground.SelectedColor;
            //    GridColor = form.rcpGrid.SelectedColor;
            //    BarStrokeColor = form.rcpBarStroke.SelectedColor;
            //    BarFillColor = form.rcpBarFill.SelectedColor;
            //    VolumeColor = form.rcpVolume.SelectedColor;
            //    LineTypeColor = form.rcpLineType.SelectedColor;
            //}
        }

        public event EventHandler<PeriodTypeChangeEventArgs> OnPeriodTypeChanged;

        public event EventHandler<ChartTypeChangeEventArgs> OnChartTypeChanged;

        public event EventHandler OnBackgourdChanged;

        public event EventHandler<IsShowVolumeChangeEventArgs> OnShowVolumeChanged;

        public ChartType ChartType
        {
            get 
            {
                return _chartType;
            }
            set 
            {
                _chartType = value;
                switch(_chartType)
                {
                    case CS.Util.ChartType.CandleStick:
                        RebindMainSeries(new CandleStickSeriesDefinition());
                        break;
                    case CS.Util.ChartType.Line:
                        RebindMainSeries(new SplineSeriesDefinition());
                        break;
                    case CS.Util.ChartType.Stick:
                        RebindMainSeries(new StickSeriesDefinition());
                        break;
                }
                if (OnChartTypeChanged != null)
                    OnChartTypeChanged(this, new ChartTypeChangeEventArgs() { chartType = _chartType });
            }
        }

        public PeriodType PeriodType
        {
            get
            {
                return _periodType;
            }
            set
            {
                _periodType = value;
                InitialChartArea();
                InitialSeries();
                GetDataFromService();
                if (OnPeriodTypeChanged != null)
                    OnPeriodTypeChanged(this, new PeriodTypeChangeEventArgs(){ periodType = _periodType});
            }
        }

        public bool IsShowVolume
        {
            get 
            {
                return _isShowVolume;
            }
            set
            {
                _isShowVolume = value;
                RebindVolumeSeries();
                if (OnShowVolumeChanged != null)
                {
                    OnShowVolumeChanged(this, new IsShowVolumeChangeEventArgs() { isShowVolue = _isShowVolume});
                }
            }
        }

        public string ProductName
        {
            get
            {
                return _productName;
            }
        }

           #endregion

        #region Context Menu Click Events
        //保存图表为图片
        private void rmiSaveToImg_Click(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {
            SaveToImage();
        }

        // 保存图表数据
        private void rmiSaveData_Click(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {
            SaveData();
        }

        private void rmiChartProperty_Click(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {
            ChartPropertySetting();
        }
        #endregion










        public new event EventHandler<ChartMouseMoveEventArgs> OnMouseMove;
    }
}
